#pragma once

#ifndef __GAME_OF_LIFE_H__
#define __GAME_OF_LIFE_H__

#include <iostream>
#include <string.h>

#ifndef ROW
    #define ROW 40
#endif

#ifndef COL
    #define COL 80
#endif

struct CELL
{
	friend class Game;
public:

	enum STATE
	{
		DEAD,
		LIFE
	};

	CELL(int percent = 50)
	{
		if (rand() % 100 >= percent)
			state = LIFE;
		else
			state = DEAD;
	}
private:
	char state : 4;
	char nums : 4;
};

class Game
{
	friend std::ostream& operator<<(std::ostream& out, const Game& g);
	friend std::istream& operator>>(std::istream& out, Game& g);
public:
	explicit Game(int row = ROW, int col = COL, int percent = 50);

	Game(const Game& g);

	Game& operator=(const Game& g);

	void Display() const
	{
		for (int i = 0; i < _row; i++)
		{
			for (int j = 0; j < _col; j++)
				putchar(_map[i][j].state == CELL::STATE::LIFE ? '#' : ' ');
			putchar('\n');
		}
	}

	void Evolution();

	~Game()
	{
		for (int i = 0; i < _row; i++)
			delete[] _map[i];
		delete[] _map;
		_map = nullptr;
	}
private:

	void SetRoundLife(int r, int c);

	void SetMap();

	const size_t _row;
	const size_t _col;
	CELL** _map;
};

#endif
